package com.yonyou.pmclouds.ncinvoker.conf;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.ncinvoker.entity.NCInvokerResult;
import com.yonyou.pmclouds.ncinvoker.entity.NCServiceVO;
import com.yonyou.pmclouds.ncinvoker.invoker.NCDirectInvoker;
import com.yonyou.pmclouds.ncinvoker.invoker.NCUBLInvoker;
import com.yonyou.pmclouds.ncinvoker.itf.NCInvoker;
import com.yonyou.pmclouds.ncinvoker.itf.NCInvokerCallBack;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 调用nc的配置
 */
@Configuration
@Slf4j
@EnableConfigurationProperties(NCInvokerProperties.class)
public class NCInvokerConfiguration {
    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES, true);
    }

    @Bean
    @ConditionalOnProperty("pmcloud.nc-invoker.nc-address")
    public NCInvoker ncDirectInvoker(NCInvokerProperties properties) {
        return new NCDirectInvoker(properties);
    }

    @Bean
    @ConditionalOnProperty("pmcloud.nc-invoker.ubl-address")
    public NCInvoker ncUBLInvoker(NCInvokerProperties properties) {
        return new NCUBLInvoker(properties);
    }

    @Bean
    @ConditionalOnMissingBean
    public NCInvoker mockeInvoker() {
        // TODO 增加一个mocker，这个mocker暂时想不好怎么写得平台化一点，就需要调用的时候，改代码吧😊
        return new NCInvoker() {
            @Override
            public NCInvokerResult invokeSync(NCServiceVO serviceVO, Map<String, Object> params, String tenant, String user) throws BusinessException {
                return null;
            }

            @Override
            public Future<NCInvokerResult> invokeAsync(NCServiceVO serviceVO, Map<String, Object> params, String tenant, String user, NCInvokerCallBack callBack) throws BusinessException {
                final NCInvokerResult result = this.invokeSync(serviceVO, params, tenant, user);
                if (callBack != null)
                    callBack.whenResult(result);
                return new Future<NCInvokerResult>() {
                    @Override
                    public boolean cancel(boolean mayInterruptIfRunning) {
                        return false;
                    }

                    @Override
                    public boolean isCancelled() {
                        return false;
                    }

                    @Override
                    public boolean isDone() {
                        return true;
                    }

                    @Override
                    public NCInvokerResult get() throws InterruptedException, ExecutionException {
                        return result;
                    }

                    @Override
                    public NCInvokerResult get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
                        return result;
                    }
                };
            }
        };
    }
}
